<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<script>
    window.onload = function () {
        // 组合使用构造函数和原型模式 自定义创建类型 实现可以共享属性和方法 也有私有的属性方法
        function Person(name, age, job) {
            this.name = name;
            this.age = age;
            this.job = job;
            this.friends = ["shelby", "Court"];
        }

        // 重写原型模式 导致只能一次性在此处添加共同的属性和方法  
        Person.prototype = {
            constructor: Person,
            sayName: function () {
                console.log(this.name);
            }
        }

        // 实例化一个新Person 对象
        var p1 = new Person("whmk", '22', 'Software Engineer');
        var p2 = new Person("jhx", '22', 'Project Engineer');

        p1.friends.push("Van");

        console.log(p1.friends);
        console.log(p2.friends);
        p1.sayName();
        p2.sayName();

        // 私有的属性和方法不相等  共享的属性方法是相等的
        console.log(p1.friends === p2.friends);//false
        console.log(p1.sayName === p2.sayName);//true

        // 添加自己的私有的属性
        p1.ok = "p1okok";
        console.log(p1)//p1okok

        // 另一种使用 继承 的思想来实现以上的功能 
        // 把b、c 的原型指向a，那么a就是他们共享的属性和方法
        let a = {
            ok: 'aaaok',
            cancel: 'nonono',
            name: 'aaa',
            sayName: function () {
                alert(this.name)
            }
        }
        //关键步骤 b、c的原型 __proto__ 指向a  类似于重写了b、c的原型对象 
        let b = Object.create(a); 
        let c = Object.create(a);

        // 而b、c同样可以实现自己的私有的属性和方法
        b.name = "bbb"
        c.name = "ccc"

        console.log(a);
        console.log(b);
        console.log(c);

        // this 谁调用this就指向谁的作用域 
        b.sayName();//bbb
        c.sayName();//ccc

    }
</script>

<body></body>

</html>